package com.terren.spider.run;

import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.transaction.TransactionStatus;

import com.terren.spider.db.service.SpiderTaskService;
import com.terren.spider.entity.biz.ArticleSearch;
import com.terren.spider.entity.common.SpiderLog;
import com.terren.spider.entity.core.Entry;
import com.terren.spider.entity.core.SpiderTask;
import com.terren.spider.run.basic.BasicSpiderRunner;
import com.terren.spider.util.common.CommonUtil;
import com.terren.spider.util.common.DateUtil;
import com.terren.spider.util.common.StringUtil;

/**
 * 支持webservice ： http://192.168.21.249:8080/spider_webservice/task?param=%E5%8C%97%E4%BA%AC,2018-03-20,2018-03-21,baiduNews-sogouNews,40,people.com
 * 
 * 
 * 
 * 关键词任务runner（原SpiderArticleSearchRunner）
 * 即 在表`t_spider_task`设置 任务，包含keyword关键字的entry都可以走这个流程，包括百度搜索，或者知乎用户抓取等
 * ## 临时任务
 * @author chengyu
 *
 */
public class SpiderKeywordTaskRunner extends BasicSpiderRunner<ArticleSearch>{

	protected SpiderTaskService spiderTaskService;// 扒取任务service
	protected SpiderTask tasks;//taskid 状态：  0 等待抓取   1抓取完成 -1抓取失败   9 抓取正在进行

	@Override
	public List<Entry> getEntrys() {
		List<Entry> entries = new ArrayList<>();
		spiderTaskService = CommonUtil.getBean(SpiderTaskService.class);
		TransactionStatus tran = null;//事务
		try {
			tran = spiderTaskService.startTransaction();//开启事务
			tasks = spiderTaskService.getOneSpiderTask();//找到spider任务
			if (null!= tasks) {
				tasks.setStatus(9);//状态设成 9 表示正在运行
				spiderTaskService.updateStatus(tasks);//状态设成 9 表示正在运行
				spiderTaskService.commitTransaction(tran);
				entries = entryService.getEntryBySourceId(tasks.getSourceId());//找到同一来源下的所有entry
				for (Entry entry : entries) {
					String keyword = tasks.getKeyword();
					Long taskId = tasks.getTaskId();
					Integer totalRecordCount = tasks.getLimit();
					String beginTime = tasks.getBeginTime();
					String endTime = tasks.getEndTime();
					//String site = tasks.getSite();
					String excludeKeyword = tasks.getExcludeKeyword();
					entry.setKeyword(keyword);
					entry.setTaskId(taskId);
					entry.setRecordLimit(totalRecordCount);
					entry.setBeginTime(beginTime);
					entry.setEndTime(endTime);
					entry.setExcludeKeyword(excludeKeyword);
					String entryUrl = entry.getEntryUrl();
					tasks.setAct(entry.getAct());
					String url = "";
					if(!tasks.getFlag()){//针对多个entry相同sourceId的关键词搜索解决关键词多次编码问题
						url = StringUtil.formatSearchUrl(getFormatTask(tasks),entryUrl);
						tasks.setFlag(true);
					}else{
						url = StringUtil.formatSearchUrl(tasks,entryUrl);
					}
					entry.setEntryUrl(url);
				}
			}
			
		} catch (Exception e) {
			log.error("SpiderKeywordTaskRunner error", e);
			taskFaild();
		} finally {
			if (tran!=null&&!tran.isCompleted()) {
				spiderTaskService.commitTransaction(tran);//提交事务
			}
		}

		return entries;
	}

	public void run() throws Exception {
		long startTime, endTime;
		startTime = System.currentTimeMillis();
		log.info("【爬虫开始】请耐心等待...");
		List<Entry> entries = getEntrys();
		for (Entry entry : entries) {
			//记录爬虫日志
			SpiderLog slog = new SpiderLog();
			String message = "抓取页面成功"+"[taskId:"+entry.getTaskId()+"]"+"[搜索引擎:"+entry.getEntryDesc()+"]"+ "[url:" + entry.getEntryUrl() + "]"+"[关键词:"+entry.getKeyword()+"]"
					+((tasks.getSite()==null||tasks.getSite().equals(""))?"":"[site:"+tasks.getSite()+"]");
			Integer status = 1;//默认成功
			Integer size = null;
			try{
				//记录爬虫日志
				slog = saveLog(entry);
				postInitEntry(entry);
				handler = spiderHandler(entry);//根据catagory创建spider handler
				String[]urls = handler.findUrl();
				size = handler.parsePage(urls);
			}catch(Exception e){
				message = e.getMessage();
				status = 0;
				throw e;
			}finally{
				postRun(entry);
				//更新爬虫日志
				updateLog(slog,entry,message,size,status);
			}
		}
		endTime = System.currentTimeMillis();
		log.info("【爬虫结束】,共耗时约" + ((endTime - startTime) / 1000 / 60) + "分。");
	}

	public void runTask() {
		while (true) {
			try {
				run();
				Thread.sleep(5000);
			} catch (Exception e) {
				
				log.error("runTask error",e);
				taskFaild();
			}
		}
	}

	

	public void taskFaild() {
		if (tasks!=null) {
			tasks.setStatus(-1);//状态设成 1 表示完成
			try {
				spiderTaskService.updateStatus(tasks);
			} catch (Exception e) {
				
				e.printStackTrace();
			}
		}

	}
	@Override
	public void postRun(Entry entry) {
		if (tasks!=null) {
			tasks.setStatus(1);//状态设成 1 表示完成
			try {
				spiderTaskService.updateStatus(tasks);
			} catch (Exception e) {
				log.error("runTask error",e);
			}
		}
	}
	/**
	 * 根据act处理不同的task
	 * @param task
	 * @return
	 * @throws Exception 
	 */
	protected SpiderTask getFormatTask(SpiderTask task) throws Exception{
		String default_charset = "utf-8";//url默认编码方式
		String keyword = StringUtil.getDealBaiduKeyWord(task.getKeyword());//关键字默认处理方式
		switch (task.getAct()) {
		case "baiduNews":// 百度新闻
			task.setKeyword(URLEncoder.encode(keyword, default_charset));
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date stdate = formatter.parse(task.getBeginTime() + " 00:00:00");
			Date etdate = formatter.parse(task.getEndTime() + " 23:59:59");
			task.setBeginTime(stdate.getTime() / 1000 + "");
			task.setEndTime(etdate.getTime() / 1000 + "");
			if(task.getSite()==null){
				task.setSite("");
			}
			break;
		case "baiduSearch":// 百度搜索
			task.setKeyword(URLEncoder.encode(keyword, default_charset));
			SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date stdate2 = formatter2.parse(task.getBeginTime() + " 00:00:00");
			Date etdate2 = formatter2.parse(task.getEndTime() + " 23:59:59");
			task.setBeginTime(stdate2.getTime() / 1000 + "");
			task.setEndTime(etdate2.getTime() / 1000 + "");
			if(task.getSite()==null){
				task.setSite("");
			}
			break;
		case "googleNews":// 谷歌新闻
			keyword = StringUtil.getDealGoogleKeyWord(task.getKeyword());
			task.setKeyword(URLEncoder.encode(keyword, default_charset));
			task.setBeginTime(DateUtil.getTruncateDateTime2(task.getBeginTime()));
			task.setEndTime(DateUtil.getTruncateDateTime2(task.getEndTime()));
			if(task.getSite()==null){
				task.setSite("");
			}else{
				task.setSite("site:"+task.getSite());
			}
			break;
		case"sogouNews":// 搜狗新闻
			task.setKeyword(URLEncoder.encode(keyword, "gb2312"));
			if(task.getSite()==null){
				task.setSite("");
			}else{
				task.setSite("site:"+task.getSite());
			}
		case "sogouSearch"://搜狗搜索
			task.setKeyword(URLEncoder.encode(keyword, "gb2312"));
			if(task.getSite()==null){
				task.setSite("");
			}else{
				task.setSite("site:"+task.getSite());
			}
			break;
		case "sogouZhihu":
			task.setKeyword(URLEncoder.encode(keyword, default_charset));
			break;
		case "xiaohongshu":
			task.setKeyword(URLEncoder.encode(keyword, default_charset));
			break;
		case "tiebaSearch":
			task.setKeyword(URLEncoder.encode(keyword, default_charset));
			break;
		case "auto.sohu.search":
			task.setKeyword(URLEncoder.encode(keyword, "gb2312"));
			break;
		case "sinablog":
			task.setKeyword(URLEncoder.encode(keyword, "gb2312"));
			break;
		case "club.autohome.com":
			task.setKeyword(URLEncoder.encode(keyword, "gb2312"));
			break;
		case "che58":
			task.setKeyword(URLEncoder.encode(keyword, "gb2312"));
			break;
		default:
			task.setKeyword(URLEncoder.encode(keyword, default_charset));
			break;
		}
		return task;
	}

}
